﻿using System;

namespace FBGraph
{
    /// <summary>Defines a contract for <see cref="IFBGraphController" /> implementations that service queries for FBGraph object connections.</summary>
    /// <typeparam name="TModel">The type of object that is returned by queries for the connection.</typeparam>
    public interface IFBGraphConnectionController<TModel> : IFBGraphController
    {
        /// <summary>In derived classes, gets the name of the connection the <see cref="IFBGraphConnectionController{TModel}" /> handles requests for.</summary>
        String ConnectionName { get; }
    }

    /// <summary>Provides querying functionality for <see cref="IFBGraphConnectionController{TModel}" /> implementations.</summary>
    public static class FBGraphConnectionControllerExtensions
    {
        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the object identified by <paramref name="id" />.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="id">The identifier of the object whose connection is being queried.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> GetFor<TModel>(this IFBGraphConnectionController<TModel> controller, Object id)
        {
            return controller.Context.GetConnection<TModel>(id, controller.ConnectionName, controller.GetFields(), null, null, null, null);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the object identified by <paramref name="id" />.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="id">The identifier of the object whose connection is being queried.</param>
        /// <param name="limit">The maximum number of objects to return.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> GetFor<TModel>(this IFBGraphConnectionController<TModel> controller, Object id, Int32 limit)
        {
            return controller.Context.GetConnection<TModel>(id, controller.ConnectionName, controller.GetFields(), null, null, limit, null);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the object identified by <paramref name="id" />.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="id">The identifier of the object whose connection is being queried.</param>
        /// <param name="limit">The maximum number of objects to return.</param>
        /// <param name="offset">The index offset from which to start returning results.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> GetFor<TModel>(this IFBGraphConnectionController<TModel> controller, Object id, Int32 limit, Int32 offset)
        {
            return controller.Context.GetConnection<TModel>(id, controller.ConnectionName, controller.GetFields(), null, null, limit, offset);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the object identified by <paramref name="id" />.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="id">The identifier of the object whose connection is being queried.</param>
        /// <param name="since">The minimum post date/time to filter results by.</param>
        /// <param name="until">The maximum post date/time to filter results by.</param>
        /// <param name="limit">The maximum number of objects to return.</param>
        /// <param name="offset">The index offset from which to start returning results.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> GetFor<TModel>(this IFBGraphConnectionController<TModel> controller, Object id, DateTime since, DateTime until, Int32 limit, Int32 offset)
        {
            return controller.Context.GetConnection<TModel>(id, controller.ConnectionName, controller.GetFields(), since, until, limit, offset);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the object identified by <paramref name="id" />.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="id">The identifier of the object whose connection is being queried.</param>
        /// <param name="paging">A <see cref="PagingOptions" /> value containing parameters for filtering and paging the results.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> GetFor<TModel>(this IFBGraphConnectionController<TModel> controller, Object id, PagingOptions paging)
        {
            return controller.Context.GetConnection<TModel>(id, controller.ConnectionName, controller.GetFields(), paging.FetchSince, paging.FetchUntil, paging.LimitCount, paging.OffsetIndex);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the currently authenticated user.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="limit">The maximum number of objects to return.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> Get<TModel>(this IFBGraphConnectionController<TModel> controller, Int32 limit)
        {
            return controller.Context.GetConnection<TModel>(null, controller.ConnectionName, controller.GetFields(), null, null, limit, null);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the currently authenticated user.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="limit">The maximum number of objects to return.</param>
        /// <param name="offset">The index offset from which to start returning results.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> Get<TModel>(this IFBGraphConnectionController<TModel> controller, Int32 limit, Int32 offset)
        {
            return controller.Context.GetConnection<TModel>(null, controller.ConnectionName, controller.GetFields(), null, null, limit, offset);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the currently authenticated user.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="since">The minimum post date/time to filter results by.</param>
        /// <param name="until">The maximum post date/time to filter results by.</param>
        /// <param name="limit">The maximum number of objects to return.</param>
        /// <param name="offset">The index offset from which to start returning results.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> Get<TModel>(this IFBGraphConnectionController<TModel> controller, DateTime since, DateTime until, Int32 limit, Int32 offset)
        {
            return controller.Context.GetConnection<TModel>(null, controller.ConnectionName, controller.GetFields(), since, until, limit, offset);
        }

        /// <summary>Gets a collection of objects associated with the connection specified by <see cref="IFBGraphConnectionController{TModel}.ConnectionName" /> for the currently authenticated user.</summary>
        /// <param name="controller">The <see cref="IFBGraphConnectionController{TModel}" /> instance.</param>
        /// <param name="paging">A <see cref="PagingOptions" /> value containing parameters for filtering and paging the results.</param>
        /// <returns>A collection of objects associated with the connection being queried.</returns>
        public static PagedResult<TModel> Get<TModel>(this IFBGraphConnectionController<TModel> controller, PagingOptions paging)
        {
            return controller.Context.GetConnection<TModel>(null, controller.ConnectionName, controller.GetFields(), paging.FetchSince, paging.FetchUntil, paging.LimitCount, paging.OffsetIndex);
        }
    }
}